﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Configuration;
using Sinacor.Infra.UI.Settings;
using Sinacor.Infra.UI.Settings.Providers;
using System.Windows;
using Sinacor.Infra.Common;
using Sinacor.Infra.UI.Messaging;
using Sinacor.Infra.UI.Messaging.Internal;
using Sinacor.Infra.UI.Common;
using Sinacor.Infra.UI.Settings;
using System.Reflection;
using Sinacor.Infra.UI.Messaging.SmartClient;
using System.Collections;
using PSE.Framework.Configuration;
using PSE.Framework.UI.Settings;

namespace Sinacor.UI.Application.Settings.SmartClient
{
    /// <summary>
    /// Classe para acesso e alteração das configurações da aplicação
    /// </summary>
    public class ApplicationSettings : System.ComponentModel.ISupportInitializeNotification
    {

        #region CurrentSetting
        private SinacorCurrentSettings _currentSettings;
        #endregion

        #region Construtor
        /// <summary>
        /// Construtor padrão
        /// </summary>
        protected ApplicationSettings()
        {
            // Carregando módulos
            ModulesConfigurationSection modules = ConfigurationManager.GetSection("modules") as ModulesConfigurationSection;
            _installedModules = new List<ModuleInformation>();

            if (modules != null)
            {
                foreach (ModuleConfigurationElement module in modules.InstalledModules)
                {
                    _installedModules.Add(new ModuleInformation(module.Name, module.Folder, module.Version));
                }
            }

            // Carregando idiomas
            LanguagesConfigurationSection languages = ConfigurationManager.GetSection("languages") as LanguagesConfigurationSection;
            _installedLanguages = new List<ClassToInstanceInformation>();

            if (languages != null)
            {
                _defaultLanguage = languages.DefaultLanguage;

                foreach (ClassToInstanceInformation language in languages.InstalledLanguages)
                {
                    _installedLanguages.Add(language);
                }
            }
            //Carregando temas iniciais
            // Carregando temas
            ThemesConfigurationSection themes = ConfigurationManager.GetSection("themes") as ThemesConfigurationSection;
            _initialThemes = new List<ClassToInstanceInformation>();
            _installedThemes = new List<ClassToInstanceInformation>();
            if (themes != null)
            {
                _defaultTheme = themes.DefaultTheme;

                foreach (ClassToInstanceInformation initialtheme in themes.InitialThemes)
                {
                    _initialThemes.Add(initialtheme);
                }
                foreach (ClassToInstanceInformation theme in themes.InstalledThemes)
                {
                    _installedThemes.Add(theme);
                }

            }

            // Obtém instância de objeto com current settings da aplicação
            _currentSettings = SinacorCurrentSettings.GetInstance();
            //Define os módulos instalados na instância de settings.
            _currentSettings.InstalledModules = _installedModules;

        }
        #endregion

        #region GetInstance
        private static ApplicationSettings _applicationSettings = null;
        /// <summary>
        /// Retorna a instancia corrente do ApplicationSettings
        /// </summary>
        /// <returns></returns>
        public static ApplicationSettings GetInstance()
        {
            // Não precisa de lock porque a primeira chamada do GetInstance sempre é feita pelo application
            if (_applicationSettings == null)
            {
                _applicationSettings = new ApplicationSettings();
            }

            return _applicationSettings;
        }
        #endregion

        /// <summary>
        /// Carrega as configurações salvas
        /// </summary>
        private void LoadLocalSettings()
        {
            IConfigurationSettings<SinacorConfigurationObjectType> configurationSettings = ConfigurationSettingsManager<SinacorConfigurationObjectType>.GetLocalConfigurationSettings();
            IConfigurationObject<SinacorConfigurationObjectType> appConfig = new ApplicationConfigurationObject();

            // Tentando carregar configurações salvas
            if (!configurationSettings.Load(ref appConfig))
            {
                // Não existem configurações salvas, inicializa valores default
                ((ApplicationConfigurationObject)appConfig).Language = this.DefaultLanguage;
                ((ApplicationConfigurationObject)appConfig).Theme = this.DefaultTheme;
                ((ApplicationConfigurationObject)appConfig).Zoom = 100;
            }

            // Preenchendo properties
            _currentSettings.CurrentLanguage = ((ApplicationConfigurationObject)appConfig).Language;
            _currentSettings.CurrentTheme = ((ApplicationConfigurationObject)appConfig).Theme;
            _currentSettings.CurrentZoom = ((ApplicationConfigurationObject)appConfig).Zoom;
        }

        /// <summary>
        /// Carrega as configurações salvas
        /// </summary>
        private void LoadServerSettings()
        {
            IConfigurationSettings<SinacorConfigurationObjectType> configurationSettings = ConfigurationSettingsManager<SinacorConfigurationObjectType>.GetServerConfigurationSettings();

            // Só recarrega settings se existir um provider remoto
            if (configurationSettings != null)
            {
                IConfigurationObject<SinacorConfigurationObjectType> appConfig = new ApplicationConfigurationObject();

                // Tentando carregar configurações salvas
                if (configurationSettings.Load(ref appConfig))
                {
                    // Se existirem configurações remotas salvas, preenche properties e salva uma cópia localmente
                    _currentSettings.CurrentLanguage = ((ApplicationConfigurationObject)appConfig).Language;
                    _currentSettings.CurrentTheme = ((ApplicationConfigurationObject)appConfig).Theme;
                    _currentSettings.CurrentZoom = ((ApplicationConfigurationObject)appConfig).Zoom;

                    ConfigurationSettingsManager<SinacorConfigurationObjectType>.GetLocalConfigurationSettings().Save(appConfig);
                }
            }
        }

        /// <summary>
        /// Salva as configurações
        /// </summary>
        private void SaveSettings()
        {
            IConfigurationSettings<SinacorConfigurationObjectType> configurationSettings = ConfigurationSettingsManager<SinacorConfigurationObjectType>.GetConfigurationSettings();
            ApplicationConfigurationObject appConfig = new ApplicationConfigurationObject();

            // Preenchendo objeto
            appConfig.Language = _currentSettings.CurrentLanguage;
            appConfig.Theme = _currentSettings.CurrentTheme;
            appConfig.Zoom = _currentSettings.CurrentZoom;

            // Tentando salvar configurações
            configurationSettings.Save((IConfigurationObject<SinacorConfigurationObjectType>)appConfig);
        }


        #region InstalledModules
        private List<ModuleInformation> _installedModules = null;
        /// <summary>
        /// Módulos instalados no sistema
        /// </summary>
        public ReadOnlyCollection<ModuleInformation> InstalledModules
        {
            get
            {
                return _installedModules.AsReadOnly();
            }
        }
        #endregion


        #region DefaultLanguage
        private string _defaultLanguage = null;
        /// <summary>
        /// Idioma default do sistema
        /// </summary>
        public string DefaultLanguage
        {
            get
            {
                return _defaultLanguage;
            }
        }
        #endregion

        #region CurrentLanguage
        //private string _currentLanguage = null;
        /// <summary>
        /// Idioma atual do sistema
        /// </summary>
        public string CurrentLanguage
        {
            get
            {
                return _currentSettings.CurrentLanguage;
            }
            protected set
            {
                if (_currentSettings.CurrentLanguage != value)
                {
                    _currentSettings.CurrentLanguage = value;
                    this.SaveSettings();
                }
            }
        }
        #endregion

        #region CurrentLanguageDictionary
        private int _currentLanguageDictionaryIndex = -1;
        /// <summary>
        /// ResourceDictionary do idioma atual do sistema
        /// </summary>
        public ResourceDictionary CurrentLanguageDictionary
        {
            get
            {
                if (_currentLanguageDictionaryIndex > -1)
                    return System.Windows.Application.Current.Resources.MergedDictionaries[_currentLanguageDictionaryIndex];
                else
                    return null;
            }
            protected set
            {
                //caso ja exista um language
                if (_currentLanguageDictionaryIndex > -1)
                {
                    //substituir
                    System.Windows.Application.Current.Resources.MergedDictionaries[_currentLanguageDictionaryIndex] = value;
                }
                else
                {
                    // Adicionando dictionary
                    System.Windows.Application.Current.Resources.MergedDictionaries.Add(value);

                    // Salvando índice do dictionary
                    _currentLanguageDictionaryIndex = System.Windows.Application.Current.Resources.MergedDictionaries.Count - 1;
                }
            }
        }
        #endregion

        #region InstalledLanguages
        private List<ClassToInstanceInformation> _installedLanguages = null;
        /// <summary>
        /// Idiomas instalados no sistema
        /// </summary>
        public ReadOnlyCollection<ClassToInstanceInformation> InstalledLanguages
        {
            get
            {
                return _installedLanguages.AsReadOnly();
            }
        }
        #endregion

        #region LoadLanguage
        /// <summary>
        /// Carrega o idioma informado
        /// </summary>
        /// <param name="language">Idioma a ser carregado</param>
        private void LoadLanguage(string language)
        {
            if (string.IsNullOrEmpty(language))
                throw new ArgumentNullException("language");

            ClassToInstanceInformation languageInfo = null;

            // Tentando encontrar assembly do idioma informado
            foreach (ClassToInstanceInformation lang in this.InstalledLanguages)
            {
                if (lang.Name == language)
                {
                    languageInfo = lang;
                    break;
                }
            }
            if (languageInfo == null)
                throw new ArgumentException(string.Format("The language '{0}' is not installed", language), "language");


            ResourceDictionary languageDictionary = null;

            // Capturando assembly de idioma
            try
            {
                if (string.IsNullOrEmpty(languageInfo.Assembly) || string.IsNullOrEmpty(languageInfo.Class))
                    throw new System.Configuration.ConfigurationException(string.Format("Invalid Class or Assembly configuration for language '{0}'", language));
                else
                    languageDictionary = GetResource(languageInfo);
            }
            catch (Exception ex)
            {
                throw new ConfigurationException(string.Format("Invalid configuration for language '{0}'", language), ex);
            }

            //se aplicacao ja esta aberta
            if (this.IsInitialized)
                //Solução de contorno para o problema de memory leak relacionado a DynamicResource + ToolTip
                WalkDictionary(languageDictionary);

            // Configurando dictionary de idiomas atual
            this.CurrentLanguageDictionary = languageDictionary;

            //se aplicacao esta sendo aberta
            if (!this.IsInitialized)
                //Solução de contorno para o problema de memory leak relacionado a DynamicResource + ToolTip
                WalkDictionary(this.CurrentLanguageDictionary);

        }
        #endregion

        #region ChangeLanguage
        /// <summary>
        /// Altera o idioma atual da aplicação
        /// </summary>
        /// <param name="language">Idioma a ser carregado</param>
        /// <returns>true se alterou com sucesso, false se idioma informado já está carregado</returns>
        public bool ChangeLanguage(string language)
        {
            if (string.IsNullOrEmpty(language))
                throw new ArgumentNullException("language");

            // Só troca se idioma for diferente do atual
            if (language != this.CurrentLanguage)
            {
                // Carregando idioma indicado
                this.LoadLanguage(language);

                // Salvando idioma atual
                this.CurrentLanguage = language;

                //Cria e dispara uma mensagem informando que a lingua do sistema foi alterada
                InternalMessage message = new InternalMessage();
                message.MessageId = MessageIds.Application.SNC_APPLICATION_LANGUAGE_CHANGED;

                WPFMessageManager messageManager = new WPFMessageManager();
                messageManager.SendMessage(message);

                return true;
            }

            return false;
        }
        #endregion

        #region DefaultTheme
        private string _defaultTheme = null;
        /// <summary>
        /// Tema default do sistema
        /// </summary>
        public string DefaultTheme
        {
            get
            {
                return _defaultTheme;
            }
        }
        #endregion

        #region CurrentTheme
        //private string _currentTheme = null;
        /// <summary>
        /// Tema atual do sistema
        /// </summary>
        public string CurrentTheme
        {
            get
            {
                return _currentSettings.CurrentTheme;
            }
            protected set
            {
                if (_currentSettings.CurrentTheme != value)
                {
                    _currentSettings.CurrentTheme = value;
                    this.SaveSettings();
                }
            }
        }
        #endregion

        #region CurrentThemeDictionary
        private int _currentThemeDictionaryIndex = -1;
        /// <summary>
        /// ResourceDictionary do tema atual do sistema
        /// </summary>
        public ResourceDictionary CurrentThemeDictionary
        {
            get
            {
                if (_currentThemeDictionaryIndex > -1)
                    return System.Windows.Application.Current.Resources.MergedDictionaries[_currentThemeDictionaryIndex];
                else
                    return null;
            }
            protected set
            {
                //caso ja exista um theme
                if (_currentThemeDictionaryIndex > -1)
                {
                    //substituir
                    System.Windows.Application.Current.Resources.MergedDictionaries[_currentThemeDictionaryIndex] = value;
                }
                else
                {
                    // Adicionando dictionary
                    System.Windows.Application.Current.Resources.MergedDictionaries.Add(value);

                    // Salvando índice do dictionary
                    _currentThemeDictionaryIndex = System.Windows.Application.Current.Resources.MergedDictionaries.Count - 1;
                }
            }
        }
        #endregion

        #region CurrentInitialThemeDictionary
        private int _currentInitialThemeDictionaryIndex = -1;
        /// <summary>
        /// ResourceDictionary do tema inicial atual do sistema
        /// </summary>
        public ResourceDictionary CurrentInitialThemeDictionary
        {
            get
            {
                if (_currentInitialThemeDictionaryIndex > -1)
                    return System.Windows.Application.Current.Resources.MergedDictionaries[_currentInitialThemeDictionaryIndex];
                else
                    return null;
            }
            protected set
            {
                //caso ja exista um initial theme
                if (_currentInitialThemeDictionaryIndex > -1)
                {
                    //substituir
                    System.Windows.Application.Current.Resources.MergedDictionaries[_currentInitialThemeDictionaryIndex] = value;
                }
                else
                {
                    // Adicionando dictionary
                    System.Windows.Application.Current.Resources.MergedDictionaries.Add(value);

                    // Salvando índice do dictionary
                    _currentInitialThemeDictionaryIndex = System.Windows.Application.Current.Resources.MergedDictionaries.Count - 1;
                }
            }
        }
        #endregion

        #region InstalledThemes
        private List<ClassToInstanceInformation> _installedThemes = null;
        /// <summary>
        /// Temas instalados no sistema
        /// </summary>
        public ReadOnlyCollection<ClassToInstanceInformation> InstalledThemes
        {
            get
            {
                return _installedThemes.AsReadOnly();
            }
        }
        #endregion

        #region initialThemes
        private List<ClassToInstanceInformation> _initialThemes = null;
        /// <summary>
        /// Temas iniciais no sistema
        /// </summary>
        public ReadOnlyCollection<ClassToInstanceInformation> InitialThemes
        {
            get
            {
                return _initialThemes.AsReadOnly();
            }
        }
        #endregion

        #region LoadInitialTheme
        /// <summary>
        /// Carrega o tema inicial
        /// </summary>
        /// <param name="theme">Thema a ser carregado</param>
        private void LoadInitialTheme(string theme)
        {
            if (string.IsNullOrEmpty(theme))
                throw new ArgumentNullException("theme");

            ClassToInstanceInformation themeInfo = null;

            // Tentando encontrar assembly do tema informado
            foreach (ClassToInstanceInformation t in this.InitialThemes)
            {
                if (t.Name == theme)
                {
                    themeInfo = t;
                    break;
                }
            }
            if (themeInfo == null)
                throw new ArgumentException(string.Format("The theme '{0}' is not installed", theme), "theme");

            ResourceDictionary themeDictionary = null;

            // Capturando assembly do tema
            try
            {
                if (string.IsNullOrEmpty(themeInfo.Class) || string.IsNullOrEmpty(themeInfo.Assembly))
                    throw new System.Configuration.ConfigurationException(string.Format("Invalid Class or Assembly configuration for theme '{0}'", theme));
                else
                    themeDictionary = GetResource(themeInfo);
            }
            catch (Exception ex)
            {
                throw new ConfigurationException(string.Format("Invalid configuration for theme '{0}'", theme), ex);
            }

            //se aplicacao ja esta aberta
            if (this.IsInitialized)
                //Solução de contorno para o problema de memory leak relacionado a DynamicResource + ToolTip
                WalkDictionary(themeDictionary);

            // Configurando dictionary de temas atual
            this.CurrentInitialThemeDictionary = themeDictionary;

            //se aplicacao esta sendo aberta
            if (!this.IsInitialized)
                //Solução de contorno para o problema de memory leak relacionado a DynamicResource + ToolTip
                WalkDictionary(this.CurrentInitialThemeDictionary);
        }

        #endregion

        #region LoadTheme
        /// <summary>
        /// Carrega o tema informado
        /// </summary>
        /// <param name="theme">Thema a ser carregado</param>
        private void LoadTheme(string theme)
        {
            if (string.IsNullOrEmpty(theme))
                throw new ArgumentNullException("theme");

            ClassToInstanceInformation themeInfo = null;

            // Tentando encontrar assembly do tema informado
            foreach (ClassToInstanceInformation t in this.InstalledThemes)
            {
                if (t.Name == theme)
                {
                    themeInfo = t;
                    break;
                }
            }
            if (themeInfo == null)
                throw new ArgumentException(string.Format("The theme '{0}' is not installed", theme), "theme");


            ResourceDictionary themeDictionary = null;

            // Capturando assembly do tema
            try
            {
                if (string.IsNullOrEmpty(themeInfo.Class) || string.IsNullOrEmpty(themeInfo.Assembly))
                    throw new System.Configuration.ConfigurationException(string.Format("Invalid Class or Assembly configuration for theme '{0}'", theme));
                else
                    themeDictionary = GetResource(themeInfo);
            }
            catch (Exception ex)
            {
                throw new ConfigurationException(string.Format("Invalid configuration for theme '{0}'", theme), ex);
            }

            //se aplicacao ja esta aberta
            if (this.IsInitialized)
                //Solução de contorno para o problema de memory leak relacionado a DynamicResource + ToolTip
                WalkDictionary(themeDictionary);

            // Configurando dictionary de temas atual
            this.CurrentThemeDictionary = themeDictionary;

            //se a aplicacao esta sendo aberta
            if (!this.IsInitialized)
                //Solução de contorno para o problema de memory leak relacionado a DynamicResource + ToolTip
                WalkDictionary(this.CurrentThemeDictionary);

        }


        private ResourceDictionary GetResource(ClassToInstanceInformation instanceInfo)
        {
            string assemblyPath = System.IO.Path.Combine(ApplicationConfiguration.GetApplicationRootDirectory(), instanceInfo.Assembly);

            Assembly resource = Assembly.LoadFrom(assemblyPath);
            string nmspace = resource.GetName().Name;

            Uri dictionary = new Uri(nmspace + @";;;component\" + instanceInfo.Class, UriKind.Relative);

            return System.Windows.Application.LoadComponent(dictionary) as ResourceDictionary;
        }

        #endregion

        #region ChangeTheme
        /// <summary>
        /// Altera o tema atual da aplicação
        /// </summary>
        /// <param name="theme">Tema a ser carregado</param>
        /// <returns>true se alterou com sucesso, false se tema informado já está carregado</returns>
        public bool ChangeTheme(string theme)
        {
            if (string.IsNullOrEmpty(theme))
                throw new ArgumentNullException("theme");

            // Só troca se tema for diferente do atual
            if (theme != this.CurrentTheme)
            {
                // Carregando tema indicado
                this.LoadTheme(theme);

                // Salvando tema atual
                this.CurrentTheme = theme;

                //Cria e dispara uma mensagem informando que o tema foi alterado
                InternalMessage message = new InternalMessage();
                message.MessageId = MessageIds.Application.SNC_APPLICATION_THEME_CHANGED;
                message.Message = theme;

                WPFMessageManager messageManager = new WPFMessageManager();
                messageManager.SendMessage(message);

                return true;
            }

            return false;
        }
        #endregion

        #region CurrentZoom
        //private double _currentZoom = -1;
        /// <summary>
        /// Zoom atual do sistema
        /// </summary>
        public int CurrentZoom
        {
            get
            {
                return _currentSettings.CurrentZoom;
            }
            protected set
            {
                if (_currentSettings.CurrentZoom != value)
                {
                    _currentSettings.CurrentZoom = value;
                    this.SaveSettings();
                }
            }
        }
        #endregion

        #region ChangeZoom
        /// <summary>
        /// Altera o zoom atual da aplicação
        /// </summary>
        /// <param name="zoomProportion">Proporção desejada de zoom a ser aplicada em toda aplicação</param>
        /// <returns>true se alterou com sucesso, false se zoom informado já está carregado</returns>
        public bool ChangeZoom(int zoomProportion)
        {
            // Só troca se idioma for diferente do atual
            if (zoomProportion != _currentSettings.CurrentZoom)
            {
                // Salva o zoom na instãncia de current settings
                //_currentSettings.CurrentZoom = zoomProportion;
                this.CurrentZoom = zoomProportion;

                //Cria e dispara uma mensagem informando que o zoom do sistema foi alterado
                InternalMessage message = new InternalMessage();
                message.MessageId = MessageIds.Application.SNC_APPLICATION_ZOOM_CHANGED;
                message.Message = zoomProportion;

                WPFMessageManager messageManager = new WPFMessageManager();
                messageManager.SendMessage(message);

                return true;
            }

            return false;
        }
        #endregion

        #region ISupportInitialize Members
        /// <summary>
        /// Carrega os settings default da aplicação
        /// </summary>
        public void BeginInit()
        {
            if (this.IsInitialized)
                throw new InvalidOperationException("Unable to BeginInit, ApplicationSettings has already been initialized");

            // Carregando os settings locais
            this.LoadLocalSettings();

            // Carregando o idoma configurado localmente na aplicação
            this.LoadLanguage(this.CurrentLanguage);

            //TODO: Ajustar o Application Settings.

            // Carregando o tema configurado localmente na aplicação

            this.LoadInitialTheme("Common");
            this.LoadTheme(this.CurrentTheme);

            //this.LoadInitialTheme("Common");
            //this.LoadTheme("Silver");           
        }

        /// <summary>
        /// Carrega os settings específicos do usuário da aplicação
        /// </summary>
        public void EndInit()
        {
            if (this.IsInitialized)
                throw new InvalidOperationException("Unable to EndInit, ApplicationSettings has already been initialized");

            // Salva idioma atual
            string currentLanguage = this.CurrentLanguage;
            // Salva tema atual
            string currentTheme = this.CurrentTheme;


            // Recarregando os settings, para capturar os settings remotos (se existirem)
            this.LoadServerSettings();


            // Verifica se idioma mudou
            if (currentLanguage != this.CurrentLanguage)
            {
                // Se mudou, carrega idioma atual
                this.LoadLanguage(this.CurrentLanguage);
            }
            // Verifica se tema mudou
            if (currentTheme != this.CurrentTheme)
            {
                // Se mudou, carrega tema atual
                this.LoadTheme(this.CurrentTheme);
            }

            // TODO: Troca de temas não vai funcionar
            this.ReloadResources("Sinacor.UI.Application.View.SmartClient.Themes.Common", this.CurrentInitialThemeDictionary);
            this.ReloadResources("Sinacor.UI.Application.View.SmartClient.Themes.Silver", this.CurrentThemeDictionary);

            // Marcando settings como Initialized
            _isInitialized = true;
            // Disparando evento Initialized
            this.OnInitialized(new EventArgs());
        }

        #endregion

        /// <summary>
        /// Está função carrega e adiciona todos os MergedDictionaries dos themas na raiz do 
        /// Application, isso é necessário para o BasedOn dos estilos funcionarem
        /// </summary>
        /// <param name="theme"></param>
        /// <param name="dic"></param>
        private void ReloadResources(string theme, ResourceDictionary dic)
        {
            foreach (ResourceDictionary child in dic.MergedDictionaries)
            {
                this.ReloadResources(theme, child);

                if (child.Source != null)
                {
                    Uri dictionary = new Uri(theme + @";;;component\" + child.Source.ToString(), UriKind.Relative);
                    System.Windows.Application.Current.Resources.MergedDictionaries.Add((ResourceDictionary)System.Windows.Application.LoadComponent(dictionary));
                }
            }
        }

        #region WalkDictionary
        /// <summary>
        /// Método que varre os dicionário de recursos da aplicação realizando assim o primeiro acesso aos mesmos.
        /// Esse método teve de ser criado devido a um bug do WPF que gera um memory leak
        /// quando associado um DynamicResource em um ToolTip.
        /// Informação extraída do seguinte endereço:
        /// http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b97a5f83-5394-430e-9a78-9d3a957e3537/
        /// </summary>
        /// <param name="resources"></param>
        private static void WalkDictionary(ResourceDictionary resources)
        {
            foreach (DictionaryEntry entry in resources) ;

            foreach (ResourceDictionary rd in resources.MergedDictionaries)
                WalkDictionary(rd);
        }
        #endregion


        #region ISupportInitializeNotification Members
        /// <summary>
        /// Evento disparado quando as configurações forem totalmente carregadas
        /// </summary>
        public event EventHandler Initialized;

        /// <summary>
        /// Dispara evento <c>Initialized</c>
        /// </summary>
        /// <param name="e">Parâmetros do evento</param>
        protected virtual void OnInitialized(EventArgs e)
        {
            if (Initialized != null)
            {
                Initialized(this, e);
            }
        }

        private bool _isInitialized = false;
        /// <summary>
        /// Indica que as configurações foram totalmente carregadas
        /// </summary>
        public bool IsInitialized
        {
            get { return _isInitialized; }
        }
        #endregion
    }
}
